package com.cskaoyan.javase.oop2.initialization6.introduction1;

/**
 * @description: 子类对象的初始化问题
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

/**
 * 我们已经学习过jvm内存中创建对象的过程，无非就是在数组的基础上加一个类加载
 * 我们今天又更进一步，Java当中每个类都有父类，这个时候如果把继承考虑进去，会发生什么变化呢
 * 因为子类要继承父类的成员，这些成员肯定不是凭空产生的，那么这个过程到底是什么样子的呢？
 *
 * 练习
 * - 创建一个Person类，有name属性和eat方法
 * - 创建一个Star类，有stageName属性和sing方法
 * - Star类要继承Person类
 * - 创建Star类对象，画出这个过程的内存图
 *
 * 子类对象中，一定是先初始化父类成员，再初始化子类成员
 * 为什么？
 * 1，因为先父后子没毛病，天经地义
 * 2，因为子类的成员变量的初始化可以依赖父类成员
 *
 * 研究一个问题：
 * Java怎么保证一定是先初始化父类成员，再初始化子类成员？
 * 老师，它就是保证了，我不关心咋保证，跟我没有关系
 * 学习是要打破砂锅问到底的精神，不仅要知道，还要知道为什么
 *
 * 有两种保证方式
 * - 隐式的调用了父类构造方法（JVM保证）
 * 在子类的构造器的第一行，默认隐式添加了一个
 * super() 调用父类的默认无参构造
 * - 程序员显式的调用父类构造方法（代码保证）
 * 程序员显式的在子类构造器的第一行 写代码
 * super(参数)调用父类的构造器
 *
 *
 *
 */
public class Demo {
    public static void main(String[] args) {
        //创建子类Star对象
        Star star = new Star();
        System.out.println(star.stageName);
    }
}

class Person {
    String name;
    public void eat() {
        System.out.println("吃饭");
    }
}
class Star extends Person {
    //子类成员变量的初始化依赖于父类成员，显然如果这个时候父类成员还没有初始化，这个地方肯定报错
    String stageName = name + "长"; //花名 艺名
    public void sing() {
        System.out.println("明星会唱歌");
    }

    //创建对象调用的是默认无参
    //如果你在这里，调用构造方法的时候，明确告诉JVM，需要先去调用父类的构造器，那么就可以达成先初始化父类成员，再初始化子类成员
    public Star() {
        //第一行告诉JVM先去调用父类构造器
        //super();
    }
}
